home *** CD-ROM | disk | FTP | other *** search
Wrap
//============================================================================== // Scn22p4: AI Scenario Script for scenario 22 player 4 //============================================================================== //============================================================================== // Set Town Location //============================================================================== void setTownLocation(void) { //Look for the "Town Location" marker. kbSetTownLocation(kbGetBlockPosition("1840")); } //============================================================================== // miscStartup //============================================================================== void miscStartup(void) { // Difficulty Level check. int difflevel=-1; difflevel=aiGetWorldDifficulty(); //Startup message(s). aiEcho(""); aiEcho(""); aiEcho("Scn22P4 AI Start, filename='"+cFilename+"'."); aiEcho("Difficulty Level="+difflevel+"."); //Spit out the map size. aiEcho(" Map size is ("+kbGetMapXSize()+", "+kbGetMapZSize()+")."); //Cheat like a bastard. Once only, though. kbLookAtAllUnitsOnMap(); //Calculate some areas. kbAreaCalculate(1200.0); //Set our town location. setTownLocation(); //Reset random seed aiRandSetSeed(); //Allocate all resources to the root escrow. kbEscrowAllocateCurrentResources(); } //============================================================================== //============================================================================== // Attack stuff. //============================================================================== //============================================================================== //Shared variables. int numberAttacks=0; int attackPlayerID=-1; //TODO: Decide how to rep attack group size. int attackMinimumGroupSize=3; int attackMaximumGroupSize=5; //Attack 1 vars. int attackPlan1ID=-1; int maintainPlan1ID=-1; //Attack 2 vars. int attackPlan2ID=-1; int maintainPlan2ID=-1; // Route and path vars int attackRoute1ID=-1; int attackPath1ID=-1; int attackRoute2ID=-1; int attackPath2ID=-1; // Unit types int attackerUnitTypeID1=cUnitTypeSpearman; int attackerUnitTypeID2=cUnitTypeSlinger; int attackerUnitTypeID3=cUnitTypeCamelry; int attackerUnitTypeID4=cUnitTypeChariotArcher; int attackerUnitTypeID5=cUnitTypeWarElephant; //========================================================================================= // Kidd's cool configQuery function: used to create attack routes, etc. Oooh, lovin' that! //========================================================================================= bool configQuery( int queryID = -1, int unitType = -1, int action = -1, int state = -1, int player = -1, vector center = vector(-1,-1,-1), bool sort = false, float radius = -1 ) { if ( queryID == -1) { return(false); } if (player != -1) kbUnitQuerySetPlayerID(queryID, player); if (unitType != -1) kbUnitQuerySetUnitType(queryID, unitType); if (action != -1) kbUnitQuerySetActionType(queryID, action); if (state != -1) kbUnitQuerySetState(queryID, state); if (center != vector(-1,-1,-1)) { kbUnitQuerySetPosition(queryID, center); if (sort == true) kbUnitQuerySetAscendingSort(queryID, true); if (radius != -1) kbUnitQuerySetMaximumDistance(queryID, radius); } return(true); } //============================================================================== // initAttack: Creates attack routes, etc. //============================================================================== void initAttack(int playerID=-1) { //Destroy all previous attacks (if this isn't the player we're already attacking. if (playerID != attackPlayerID) { //Reset the attack player ID. attackPlayerID=-1; //Destroy any previous attack plan. aiPlanDestroy(attackPlan1ID); attackPlan1ID=-1; aiPlanDestroy(attackPlan2ID); attackPlan2ID=-1; //Destroy our previous attack paths. kbPathDestroy(attackPath1ID); attackPath1ID=-1; kbPathDestroy(attackPath2ID); attackPath2ID=-1; //Destroy our previous attack routes. attackRoute1ID=-1; attackRoute2ID=-1; //Reset the number of attacks. numberAttacks=0; } //Save the player to attack. attackPlayerID=playerID; vector gatherPointForward=kbGetBlockPosition("1844"); vector gatherPointRear=kbGetBlockPosition("1840"); //Setup attack path 1 - N/A; forward attack (no waypoints) attackPath1ID=kbPathCreate("Attack Path 1"); //Create attack route 1 (from gather point) attackRoute1ID=kbCreateAttackRouteWithPath("Attack Route 1", gatherPointForward, kbGetBlockPosition("1845")); if (attackRoute1ID >= 0) kbAttackRouteAddPath(attackRoute1ID, attackPath1ID); //Setup attack path 2 - from the rear attackPath2ID=kbPathCreate("Attack Path 2"); kbPathAddWaypoint(attackPath2ID, kbGetBlockPosition("1841")); kbPathAddWaypoint(attackPath2ID, kbGetBlockPosition("1842")); kbPathAddWaypoint(attackPath2ID, kbGetBlockPosition("1843")); kbPathAddWaypoint(attackPath2ID, kbGetBlockPosition("1844")); //Create attack route 2. attackRoute2ID=kbCreateAttackRouteWithPath("Attack Route 2", gatherPointRear, kbGetBlockPosition("1845")); if (attackRoute2ID >= 0) kbAttackRouteAddPath(attackRoute2ID, attackPath2ID); } //============================================================================== // setupForwardAttack //============================================================================== bool setupForwardAttack(int playerID=-1) { //Info. aiEcho("Attacking Player "+playerID+"."); //If the player to attack doesn't match, init the attack. if (attackPlayerID != playerID) { initAttack(playerID); if (attackPlayerID < 0) return(false); } //Create an attack plan. int newAttackPlanID=aiPlanCreate("Attack Player"+attackPlayerID+" Attempt"+numberAttacks, cPlanAttack); if (newAttackPlanID < 0) return(false); //Target player (required). This must work. if (aiPlanSetVariableInt(newAttackPlanID, cAttackPlanPlayerID, 0, attackPlayerID) == false) return(false); //Gather point. vector gatherPoint=kbGetBlockPosition("1844"); //Set the target type. This must work. if (aiPlanSetNumberVariableValues(newAttackPlanID, cAttackPlanTargetTypeID, 2, true) == false) return(false); //Unit types to attack. aiPlanSetVariableInt(newAttackPlanID, cAttackPlanTargetTypeID, 0, cUnitTypeUnit); aiPlanSetVariableInt(newAttackPlanID, cAttackPlanTargetTypeID, 1, cUnitTypeBuilding); aiPlanSetVariableInt(newAttackPlanID, cAttackPlanAttackRouteID, 0, attackRoute1ID); //Set the gather point and gather point distance. aiPlanSetVariableVector(newAttackPlanID, cAttackPlanGatherPoint, 0, gatherPoint); aiPlanSetVariableFloat(newAttackPlanID, cAttackPlanGatherDistance, 0, 15.0); //Set up the attack route usage pattern. aiPlanSetVariableInt(newAttackPlanID, cAttackPlanAttackRoutePattern, 0, cAttackPlanAttackRoutePatternRandom); //Add the unit types to the plan - always spearmen, whatever slingers are available. aiPlanAddUnitType(newAttackPlanID, attackerUnitTypeID1, attackMinimumGroupSize, attackMaximumGroupSize, attackMaximumGroupSize); aiPlanAddUnitType(newAttackPlanID, attackerUnitTypeID2, 0, attackMaximumGroupSize, attackMaximumGroupSize); //Set the initial position. aiPlanSetInitialPosition(newAttackPlanID, gatherPoint); //Plan requires all need units to work (can be false). aiPlanSetRequiresAllNeedUnits(newAttackPlanID, true); //Activate the plan. aiPlanSetActive(newAttackPlanID); //Now, save the attack plan ID appropriately. aiPlanSetOrphan(attackPlan1ID, true); attackPlan1ID=newAttackPlanID; //Increment our overall number of attacks. numberAttacks++; } //============================================================================== // setupRearAttack //============================================================================== bool setupRearAttack(int playerID=-1) { //Info. aiEcho("Attacking Player "+playerID+"."); //If the player to attack doesn't match, init the attack. if (attackPlayerID != playerID) { initAttack(playerID); if (attackPlayerID < 0) return(false); } //Create an attack plan. int newAttackPlanID=aiPlanCreate("Attack Player"+attackPlayerID+" Attempt"+numberAttacks, cPlanAttack); if (newAttackPlanID < 0) return(false); //Target player (required). This must work. if (aiPlanSetVariableInt(newAttackPlanID, cAttackPlanPlayerID, 0, attackPlayerID) == false) return(false); //Gather point. vector gatherPoint=kbGetBlockPosition("1840"); //Set the target type. This must work. if (aiPlanSetNumberVariableValues(newAttackPlanID, cAttackPlanTargetTypeID, 2, true) == false) return(false); //Unit types to attack. aiPlanSetVariableInt(newAttackPlanID, cAttackPlanTargetTypeID, 0, cUnitTypeUnit); aiPlanSetVariableInt(newAttackPlanID, cAttackPlanTargetTypeID, 1, cUnitTypeBuilding); aiPlanSetVariableInt(newAttackPlanID, cAttackPlanAttackRouteID, 0, attackRoute2ID); //Set the gather point and gather point distance. aiPlanSetVariableVector(newAttackPlanID, cAttackPlanGatherPoint, 0, gatherPoint); aiPlanSetVariableFloat(newAttackPlanID, cAttackPlanGatherDistance, 0, 15.0); //Set up the attack route usage pattern aiPlanSetVariableInt(newAttackPlanID, cAttackPlanAttackRoutePattern, 0, cAttackPlanAttackRoutePatternRandom); //Add the unit types to the plan. Camels and chariots and elephants, oh my. aiPlanAddUnitType(newAttackPlanID, attackerUnitTypeID3, 1, 2, 4); aiPlanAddUnitType(newAttackPlanID, attackerUnitTypeID4, 0, 2, 3); aiPlanAddUnitType(newAttackPlanID, attackerUnitTypeID5, 0, 1, 2); //Set the initial position. aiPlanSetInitialPosition(newAttackPlanID, gatherPoint); //Plan requires all need units to work (can be false). aiPlanSetRequiresAllNeedUnits(newAttackPlanID, true); //Activate the plan. aiPlanSetActive(newAttackPlanID); //Now, save the attack plan ID appropriately. aiPlanSetOrphan(attackPlan2ID, true); attackPlan2ID=newAttackPlanID; //Increment our overall number of attacks. numberAttacks++; } //============================================================================== // Queryin' for enemies near the first TC (for Ancestors) //============================================================================== int checkForEnemies(void) { static int enemyQueryID=-1; vector firstTC=kbGetBlockPosition("1844"); int enemyCount=-1; if (enemyQueryID < 0) { // Doesn't exist, set it up enemyQueryID = kbUnitQueryCreate("Enemies at TC Query"); // Get the number if ( configQuery( enemyQueryID, cUnitTypeUnit, -1, cUnitStateAlive, 1, firstTC, false, 15 ) == false ) return(-1); } kbUnitQueryResetResults(enemyQueryID); enemyCount = kbUnitQueryExecute(enemyQueryID); return(enemyCount); } //============================================================================== // Queryin' for enemies at the gate (to trigger attacks) //============================================================================== int checkForEnemiesAtGate(void) { static int enemyQueryID=-1; vector mainGate=kbGetBlockPosition("1845"); int enemyCount=-1; if (enemyQueryID < 0) { // Doesn't exist, set it up enemyQueryID = kbUnitQueryCreate("Enemies at Gate Query"); // Get the number if ( configQuery( enemyQueryID, cUnitTypeUnit, -1, cUnitStateAlive, 1, mainGate, false, 15 ) == false ) return(-1); } kbUnitQueryResetResults(enemyQueryID); enemyCount = kbUnitQueryExecute(enemyQueryID); return(enemyCount); } //============================================================================== // Rule to check for enemies close to the TC - if so, use Ancestors at the TC. //============================================================================== rule castAncestors minInterval 10 inactive group GodPowerRules { int numEnemies=-1; vector ancestorsPoint=kbGetBlockPosition("1844"); numEnemies=checkForEnemies(); if (numEnemies > 4) { aiEcho("Enemies close to TC, cast Ancestors."); if ( aiCastGodPowerAtPosition(cTechSkeletonPower, ancestorsPoint) == true ) xsDisableSelf(); else aiEcho("Ancestors failed - try again later."); } } //============================================================================== // Fire Vision, two minutes in. //============================================================================== rule castVision minInterval 120 active group GodPowerRules { vector visionPoint=kbGetBlockPosition("1847"); aiEcho("Cast Vision near enemy TC"); if ( aiCastGodPowerAtPosition(cTechVision, visionPoint) == true ) xsDisableSelf(); else aiEcho("Vision failed - try again later."); } //============================================================================== // Attack Generator 1 - Forward Infantry Group //============================================================================== rule attackGenerator1 minInterval 75 inactive group AttackRules runImmediately { //See how many "idle" attack plans we have. Don't create any more if we have //idle plans. // int numberIdleAttackPlans=aiGetNumberIdlePlans(cPlanAttack); // DP's check taken out. Let them be idle!!! // if (numberIdleAttackPlans > 0) // return; //If we have enough unassigned military units, create a new attack plan. int numberAvailableUnits=aiNumberUnassignedUnits(attackerUnitTypeID1); aiEcho("There are "+numberAvailableUnits+" spearmen available for a new attack."); if (numberAvailableUnits >= attackMinimumGroupSize) setupForwardAttack(1); } //============================================================================== // Attack Generator 2 - Cavalry Group //============================================================================== rule attackGenerator2 minInterval 90 inactive group AttackRules runImmediately { //See how many "idle" attack plans we have. Don't create any more if we have //idle plans. // int numberIdleAttackPlans=aiGetNumberIdlePlans(cPlanAttack); // DP's check taken out. Let them be idle!!! // if (numberIdleAttackPlans > 0) // return; //If we have enough unassigned military units, create a new attack plan. int numberAvailableUnits=aiNumberUnassignedUnits(attackerUnitTypeID3); aiEcho("There are "+numberAvailableUnits+" camelry available for a new attack."); if (numberAvailableUnits >= 2) setupRearAttack(1); } //============================================================================== // Rule to check for three enemies close to the gate - activates initial attacks //============================================================================== rule attack1Enabler minInterval 15 active group AttackRules { int numEnemies=-1; numEnemies=checkForEnemiesAtGate(); if (numEnemies > 2) { aiEcho("*** QUERY: Enemy at the gates, activating attacks."); xsEnableRule("attackGenerator1"); xsEnableRule("castAncestors"); xsDisableSelf(); } } //===================================================================================== // Attack Launcher. This is called from the scenario with an AI Func effect // when the player severely damages the forward settlement. //===================================================================================== void attackLauncher(int whichAttack = -1) { aiEcho("*** FORWARD SETTLEMENT DAMAGED - ATTACK LAUNCHER CALLED ***"); xsEnableRule("attackGenerator2"); } //============================================================================== // MAIN. //============================================================================== void main(void) { //Startup. miscStartup(); //Share the number to maintain. int numberToMaintain=attackMinimumGroupSize*2; //Two gather points possible. vector gatherPointForward=kbGetBlockPosition("1844"); vector gatherPointRear=kbGetBlockPosition("1840"); //Maintain X spearmen. int maintainPlan1ID=aiPlanCreate("Maintain "+numberToMaintain+" "+kbGetProtoUnitName(attackerUnitTypeID1), cPlanTrain); if (maintainPlan1ID >= 0) { //Must set the type of unit to train. aiPlanSetVariableInt(maintainPlan1ID, cTrainPlanUnitType, 0, attackerUnitTypeID1); //You can limit the number of units that are ever trained by this plan with this call. //aiPlanSetVariableInt(maintainPlanID, cTrainPlanNumberToTrain, 0, 25); //Set the number of units to maintain in the world at one time. aiPlanSetVariableInt(maintainPlan1ID, cTrainPlanNumberToMaintain, 0, numberToMaintain); //Don't train units too fast aiPlanSetVariableInt(maintainPlan1ID, cTrainPlanFrequency, 0, 20); //Set a gather point. aiPlanSetVariableVector(maintainPlan1ID, cTrainPlanGatherPoint, 0, gatherPointForward); //Activate the plan. aiPlanSetActive(maintainPlan1ID); } //Maintain X slingers. int maintainPlan2ID=aiPlanCreate("Maintain "+numberToMaintain+" "+kbGetProtoUnitName(attackerUnitTypeID2), cPlanTrain); if (maintainPlan2ID >= 0) { //Must set the type of unit to train. aiPlanSetVariableInt(maintainPlan2ID, cTrainPlanUnitType, 0, attackerUnitTypeID2); //You can limit the number of units that are ever trained by this plan with this call. //aiPlanSetVariableInt(maintainPlanID, cTrainPlanNumberToTrain, 0, 25); //Set the number of units to maintain in the world at one time. aiPlanSetVariableInt(maintainPlan2ID, cTrainPlanNumberToMaintain, 0, numberToMaintain); //Don't train units too fast aiPlanSetVariableInt(maintainPlan2ID, cTrainPlanFrequency, 0, 30); //Set a gather point. aiPlanSetVariableVector(maintainPlan2ID, cTrainPlanGatherPoint, 0, gatherPointForward); //Activate the plan. aiPlanSetActive(maintainPlan2ID); } //Maintain 4 camelry. int maintainPlan3ID=aiPlanCreate("Maintain "+numberToMaintain+" "+kbGetProtoUnitName(attackerUnitTypeID3), cPlanTrain); if (maintainPlan3ID >= 0) { //Must set the type of unit to train. aiPlanSetVariableInt(maintainPlan3ID, cTrainPlanUnitType, 0, attackerUnitTypeID3); //You can limit the number of units that are ever trained by this plan with this call. //aiPlanSetVariableInt(maintainPlanID, cTrainPlanNumberToTrain, 0, 25); //Set the number of units to maintain in the world at one time. aiPlanSetVariableInt(maintainPlan3ID, cTrainPlanNumberToMaintain, 0, 4); //Don't train units too fast aiPlanSetVariableInt(maintainPlan3ID, cTrainPlanFrequency, 0, 30); //Set a gather point. aiPlanSetVariableVector(maintainPlan3ID, cTrainPlanGatherPoint, 0, gatherPointRear); //Activate the plan. aiPlanSetActive(maintainPlan3ID); } //Maintain 3 chariot archers. int maintainPlan4ID=aiPlanCreate("Maintain 3 "+kbGetProtoUnitName(attackerUnitTypeID4), cPlanTrain); if (maintainPlan4ID >= 0) { //Must set the type of unit to train. aiPlanSetVariableInt(maintainPlan4ID, cTrainPlanUnitType, 0, attackerUnitTypeID4); //You can limit the number of units that are ever trained by this plan with this call. //aiPlanSetVariableInt(maintainPlanID, cTrainPlanNumberToTrain, 0, 25); //Set the number of units to maintain in the world at one time. aiPlanSetVariableInt(maintainPlan4ID, cTrainPlanNumberToMaintain, 0, 3); //Don't train units too fast aiPlanSetVariableInt(maintainPlan4ID, cTrainPlanFrequency, 0, 45); //Set a gather point. aiPlanSetVariableVector(maintainPlan4ID, cTrainPlanGatherPoint, 0, gatherPointRear); //Activate the plan. aiPlanSetActive(maintainPlan4ID); } //Maintain 2 elephants int maintainPlan5ID=aiPlanCreate("Maintain 2 "+kbGetProtoUnitName(attackerUnitTypeID5), cPlanTrain); if (maintainPlan5ID >= 0) { //Must set the type of unit to train. aiPlanSetVariableInt(maintainPlan5ID, cTrainPlanUnitType, 0, attackerUnitTypeID5); //You can limit the number of units that are ever trained by this plan with this call. //aiPlanSetVariableInt(maintainPlanID, cTrainPlanNumberToTrain, 0, 25); //Set the number of units to maintain in the world at one time. aiPlanSetVariableInt(maintainPlan5ID, cTrainPlanNumberToMaintain, 0, 2); //Don't train units too fast aiPlanSetVariableInt(maintainPlan5ID, cTrainPlanFrequency, 0, 60); //Set a gather point. aiPlanSetVariableVector(maintainPlan5ID, cTrainPlanGatherPoint, 0, gatherPointRear); //Activate the plan. aiPlanSetActive(maintainPlan5ID); } }